﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Nature.Data
{

    

    public interface ISpeciesThermo7Contract
    {
        string SpeciesID { get; }

        IEnumerable<Thermo7Range> RangeCollections { get; }        
    }

    public partial class AtomsPerMoleculeAmount
    {
        public ChemicalElement Element { get; internal set; }

        public ChemicalSpecies Species { get; internal set; }
    }

    


    [DebuggerDisplay("{SpeciesID}")]
    public partial class ChemicalSpecies
    {
        public ReadOnlyArray<AtomsPerMoleculeAmount> AtomsPerMoleculeAmounts { get; internal set; }


    }

    [DebuggerDisplay("{ElementID}")]
    public partial class ChemicalElement
    {
        

        public ReadOnlyArray<AtomsPerMoleculeAmount> AtomsPerMoleculeAmounts { get; internal set; }
    }

    [DebuggerDisplay("{AtomsPerMolecule} atoms of {ElementID} in {SpeciesID}")]
    public partial class AtomsPerMoleculeAmount { }


    public partial struct Thermo7Range
    {
        public Thermo7Range(double tmin, double tmax,
            double a1, double a2, double a3, double a4, double a5, 
            double a6, double a7) : this()
        {
            this.Tmin = tmin;
            this.Tmax = tmax;
            this.A1 = a1;
            this.A2 = a2;
            this.A3 = a3;
            this.A4 = a4;
            this.A5 = a5;
            this.A6 = a6;
            this.A7 = a7;
            OnCreated();
        }
    }

    public partial class Thermo7
    {
        public Thermo7(ISpeciesThermo7Contract contract) : this()
        {
            SpeciesID = contract.SpeciesID;
            Ranges = new ReadOnlyArray<Thermo7Range>(
                    contract.RangeCollections.OrderBy(i=> i.Tmin)
                    .ToArray()
                );
        }

        public ChemicalSpecies Species { get; internal set; }
    }

    public partial class GasKinParameters
    {      

        public ChemicalSpecies Species { get; internal set; }

        public bool IsPolar { get { return this.Alpha != 0.0; } }

        /// <summary>
        /// Rotational relaxation collision factor F(T) 
        /// </summary>
        public double RotRelCollFactor(double temperature)
        {
            double f;
            double re = this.Epsilon / temperature;
            double sqrt_re = Math.Sqrt(re);
            double pi_3_2 = 5.568327996831708;
            f = 1.0;
            f += 0.5 * pi_3_2 * sqrt_re;
            f += (0.25 * Math.PI * Math.PI + 2.0) * re;
            f += pi_3_2 * re * sqrt_re;
            return (f);
        }

        internal GasKinParameters(GasKinParameters v1, GasKinParameters v2)
        {
            Epsilon = Math.Sqrt(v1.Epsilon * v2.Epsilon);
            Sigma = 0.5 * (v1.Sigma + v2.Sigma);
            if (v1.IsPolar == v2.IsPolar)
            {
                Mu = Math.Sqrt(v1.Mu * v2.Mu);
            }
            else
            {
                GasKinParameters n = v1, p = v2;
                if (v1.IsPolar) { n = v2; p = v1; }
                double ksy = 1.0 + 0.25 * n.Alpha * p.Mu * Math.Sqrt(p.Epsilon / n.Epsilon);
                Mu = 0.0;
                Epsilon *= (ksy * ksy);
                Sigma /= Math.Pow(ksy, 1.0 / 6.0);
            }
        }
    }
}
